package br.academia.controller;

import java.util.ArrayList;
import java.util.Collection;

import javax.faces.model.SelectItem;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import br.academia.arq.dao.CidadeDAO;
import br.academia.arq.erros.DAOException;
import br.academia.arq.erros.NegocioException;
import br.academia.dominio.Cidade;
import br.academia.dominio.Estado;
import br.academia.negocio.AbstractProcessador;
import br.academia.negocio.CidadeProcessador;
import br.academia.util.Validador;

@SuppressWarnings("serial")
@Component("cidade")
@Scope("session")
public class CidadeController extends AbstractController{
	/** JSPs chamadas pelo Controller */
	public static final String CADASTRAR_JSP = "/admin/cidade/cadastrar_cidade.jsf";
	public static final String ALTERAR_JSP = "/admin/cidade/alterar_cidade.jsf";
	public static final String LISTAR_JSP = "/admin/cidade/listar_cidade.jsf";
	public static final String MENU_JSP = "/admin/cidade/menu_cidade.jsf";
	
	/** Objeto usado nos fluxos do Controller */
	private Cidade cidade;
	
	/** Atributos usados nas listagens do Controller */
	private boolean buscaNome;
	private boolean buscaNomeReduzido;
	private boolean buscaEstado;
	private String nome;
	private Estado estado;
	
	/** Lista populada pelos fluxos */
	private Collection<Cidade> listaCidades;
	
	/** Combo de Cidades */
	private Collection<SelectItem> comboCidades;
	private Integer idEstadoSelecionadoComboCidades;
	
	protected void carregarComboCidadesByEstado(Integer idEstado){
		if(Validador.isEmpty(comboCidades) || idEstado != idEstadoSelecionadoComboCidades){
			CidadeDAO dao = null;
			try {
				dao = getDAO(CidadeDAO.class);
				
				Estado est = new Estado();
				est.setId(idEstado);
				
				comboCidades = toSelectItems(dao.findCidadeByEstado(est), "id", "nomeFormatado");
				idEstadoSelecionadoComboCidades = idEstado;
			} catch (DAOException e) {
				addMensagem("Ocorreu um erro na geração da lista de Cidades. Por favor, contate a administração do sistema.");
				postarMensagens();
				e.printStackTrace();
			}finally{
				close(dao);
			}
		}
	}
	
	public Collection<SelectItem> getComboCidades(){
		if(comboCidades == null){
			comboCidades = new ArrayList<SelectItem>();
		}
		return comboCidades;
	}
	
	/**
	 * Construtor público
	 */
	public CidadeController(){
		reset();
	}
	
	/**
	 * Método usado para reiniciar os atributos do Controller
	 */
	public void reset(){
		cidade = new Cidade();
		listaCidades = new ArrayList<Cidade>();
		buscaNome = false;
		buscaNomeReduzido = false;
		buscaEstado = false;
		nome = "";
		estado = new Estado();
	}
	
	/**
	 * Método utilizado para entrar no menu de Cidade
	 * @return
	 */
	public String entrarMenu(){
		reset();
		
		return forward(MENU_JSP);
	}
	
	/**
	 * Método utilizado para entrar na listagem de Cidade
	 * @return
	 */
	public String entrarListagem(){
		reset();
		
		return forward(LISTAR_JSP);
	}
	
	/**
	 * Método que popula a lista de Cidades e redireciona para a listagem
	 * @return
	 */
	public String listar(){
		CidadeDAO dao = null;
		
		try {
			dao = getDAO(CidadeDAO.class);
			
			if(Validador.isEmpty(nome) && Validador.isEmpty(estado)){
				addMensagem("Por favor, insira pelo menos um parâmetro de busca.");
			}else{
				if(hasMensagens()){
					return reload();
				}
				
				setValores();
				
				listaCidades = dao.findCidadeLike(cidade);
			}
		} catch (DAOException e) {
			addMensagem("Ocorreu um erro na listagem de cidades. Por favor, contate a administração do sistema.");
			e.printStackTrace();
			return reload();
		}finally{
			if(dao != null){
				dao.close();
			}
		}
		
		if(hasMensagens()){
			return reload();
		}
		
		if(listaCidades.isEmpty()){
			addMensagem("Não foi encontrada nenhuma Cidade para a busca realizada.");
		}
		
		return forward(LISTAR_JSP);
	}
	
	/**
	 * Método utilizado para entrar na página de alteração de Cidades
	 * @return
	 */
	public String entrarAlteracao(){
		reset();
		CidadeDAO dao = null;
		
		Integer id = Integer.valueOf(getParameter("id"));
		
		if(id == null || id <= 0){
			addMensagem("Ocorreu um erro na alteração da cidade selecionada. Por favor, contate a administração do sistema.");
			return reload();
		}
		
		try {
			dao = getDAO(CidadeDAO.class);
			
			cidade = dao.findByPrimaryKey(id, Cidade.class);
			
			estado = cidade.getEstado();
		} catch (DAOException e) {
			e.printStackTrace();
		}finally{
			close(dao);
		}
		
		return forward(ALTERAR_JSP);
	}
	
	/**
	 * Método que realiza a chamada à classe de negócio que realiza
	 * a atualização da Cidade na base de dados.
	 * @return
	 */
	public String alterar(){
		addMensagem(Validador.validaPreenchimento("Nome", cidade.getNome()));
		addMensagem(Validador.validaPreenchimento("Estado", estado));
		
		if(hasMensagens()){
			return reload();
		}
		
		setValores();
		
		CidadeProcessador processador = new CidadeProcessador();
		
		try {
			processador.execute(AbstractProcessador.ALTERAR, cidade);
		} catch (NegocioException e) {
			addMensagem(e.getMessage());
		}
		
		if(hasMensagens()){
			return reload();
		}
		
		addMensagem(mensagemSucesso);
		
		return entrarListagem();
	}
	
	/**
	 * Método utilizado para entrar na página de cadastro de Cidades
	 * @return
	 */
	public String entrarCadastro(){
		reset();
		
		return forward(CADASTRAR_JSP);
	}
	
	/**
	 * Método que realiza a chamada à classe de negócio que realiza
	 * a inserção da Cidade na base de dados.
	 * @return
	 */
	public String cadastrar(){
		addMensagem(Validador.validaPreenchimento("Nome", nome));
		addMensagem(Validador.validaPreenchimento("Estado", estado));
		
		if(hasMensagens()){
			return reload();
		}
		
		setValores();
		
		CidadeProcessador processador = new CidadeProcessador();
		
		try {
			processador.execute(AbstractProcessador.CADASTRAR, cidade);
		} catch (NegocioException e) {
			addMensagem(e.getMessage());
		}
		
		if(hasMensagens()){
			return reload();
		}
		
		addMensagem(mensagemSucesso);
		
		return entrarListagem();
	}
	
	/**
	 * Método utilizado na página de listagem de Cidades, para remover
	 * uma Cidade selecionada.
	 * @return
	 */
	public String remover(){
		Integer id = Integer.valueOf(getParameter("id"));
		
		if(id == null || id <= 0){
			addMensagem("Ocorreu um erro na remoção do item selecionado. Por favor, contate a administração do sistema.");
			return reload();
		}
		
		cidade.setId(id);
		
		CidadeProcessador processador = new CidadeProcessador();
		
		try {
			processador.execute(AbstractProcessador.REMOVER, cidade);
		} catch (NegocioException e) {
			addMensagem(e.getMessage());
		}
		
		if(hasMensagens()){
			return reload();
		}
		
		addMensagem(mensagemSucesso);
		
		return entrarListagem();
	}
	
	/**
	 * Método utilizado para cancelar a operação em curso
	 * @return
	 */
	public String cancelar(){
		return entrarMenu();
	}
	
	private void setValores(){
		cidade.setNome(nome.trim());
		cidade.setEstado(estado);
	}

	public void setBuscaNome(boolean buscaNome) {
		this.buscaNome = buscaNome;
	}

	public boolean isBuscaNome() {
		return buscaNome;
	}
	
	public Cidade getCidade() {
		return cidade;
	}

	public void setCidade(Cidade cidade) {
		this.cidade = cidade;
	}

	public boolean isBuscaNomeReduzido() {
		return buscaNomeReduzido;
	}

	public void setBuscaNomeReduzido(boolean buscaNomeReduzido) {
		this.buscaNomeReduzido = buscaNomeReduzido;
	}

	public boolean isBuscaEstado() {
		return buscaEstado;
	}

	public void setBuscaEstado(boolean buscaEstado) {
		this.buscaEstado = buscaEstado;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public Estado getEstado() {
		return estado;
	}

	public void setEstado(Estado estado) {
		this.estado = estado;
	}

	public Collection<Cidade> getListaCidades() {
		return listaCidades;
	}

	public void setListaCidades(Collection<Cidade> listaCidades) {
		this.listaCidades = listaCidades;
	}

}
